/////////////////////////////////////////////////////////////////////////////
// Name:        tts_process.h
// Purpose:     Helpers for external process TTS handlers
// Author:      Julian Smart
// Modified by: 
// Created:     2009-02-10
// RCS-ID:      
// Copyright:   (c) Julian Smart
// Licence:     New BSD License
/////////////////////////////////////////////////////////////////////////////

#ifndef _WX_TTS_PROCESS_
#define _WX_TTS_PROCESS_

/*
 * Includes
 */

#include "wx/process.h"
#include "tts/tts.h"

/**
    @class wxTTSExternalCommandHandler
    
    @category{tts}
 */

class wxTTSExternalCommandHandlerProcess;

class wxTTSExternalCommandHandler: public wxTTSHandler
{    
    DECLARE_CLASS( wxTTSExternalCommandHandler )

public:
// Constructors

    wxTTSExternalCommandHandler(const wxString& id, const wxString& displayName);
    ~wxTTSExternalCommandHandler();

// Operations

    /// Member initialisation
    void Init();

    /// Initialize the engine. Can call multiple times.
    virtual bool Initialize() { return true; }

    /// Clean up the engine. Can call multiple times.
    virtual bool Uninitialize() { return true; }

    /// Is it speaking?
    virtual bool IsSpeaking() const { return (GetProcess() != NULL); }

    /// Stop speaking
    virtual bool Stop();

    /// Launch command
    virtual bool Launch(const wxString& cmd, int options);

    /// The voice names can be the same.
    virtual bool VoicesAreCompatible(const wxString& voice1, const wxString& voice2) const;

    /// Set/get the last command
    void SetLastCommand(const wxString& command) { m_command = command; }
    wxString GetLastCommand() const { return m_command; }

    /// Set/get the error code
    void SetErrorCode(int errorCode) { m_errorCode = errorCode; }
    int GetErrorCode() const { return m_errorCode; }

    /// Set/get the process id
    void SetPID(long pid) { m_pid = pid; }
    long GetPID() const { return m_pid; }

    /// Set/get the output from the command
    void SetOutput(const wxArrayString& output) { m_output = output; }
    const wxArrayString& GetOutput() const { return m_output; }

    /// Process any pending input
    virtual bool ProcessInput();

    /// Add a line of output
    virtual void WriteOutput(const wxString& output) { m_output.Add(output); }

    /// Set/get process
    void SetProcess(wxTTSExternalCommandHandlerProcess* process) { m_process = process; }
    wxTTSExternalCommandHandlerProcess* GetProcess() const { return m_process; }

    /// Cannot safely start engine while another is in a yield loop,
    /// so test this and fail if necessary.
    static bool IsStopping() { return sm_stopping > 0; }

protected:
    wxString                            m_command;
    wxArrayString                       m_output;
    int                                 m_errorCode;
    wxTTSExternalCommandHandlerProcess* m_process;
    long                                m_pid;
    static int                          sm_stopping;
};

/*!
 * wxTTSExternalCommandHandlerProcess base class declaration
 */

class wxTTSExternalCommandHandlerProcess: public wxProcess
{
public:
    DECLARE_CLASS(wxTTSExternalCommandHandlerProcess)

    wxTTSExternalCommandHandlerProcess(const wxString& cmd, wxTTSExternalCommandHandler* speechHandler, wxEvtHandler* handler): wxProcess(handler, wxPROCESS_REDIRECT), m_cmd(cmd)
    {
        m_eventHandler = handler;
        m_handler = speechHandler;
        Redirect();
    }

    virtual void OnTerminate(int pid, int status);

    virtual bool HasInput();

protected:
    wxString                        m_cmd;
    wxEvtHandler*                   m_eventHandler;
    wxTTSExternalCommandHandler*    m_handler;
};

#endif
    // _WX_TTS_PROCESS_
